package com.example.vault.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Redis服务类
 * 提供缓存、会话管理和分布式锁功能
 */
@Service
public class RedisService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    @Qualifier("cacheRedisTemplate")
    private RedisTemplate<String, Object> cacheRedisTemplate;

    @Autowired
    @Qualifier("sessionRedisTemplate")
    private RedisTemplate<String, Object> sessionRedisTemplate;

    @Autowired
    @Qualifier("lockRedisTemplate")
    private RedisTemplate<String, String> lockRedisTemplate;

    // ==================== 缓存操作 ====================

    /**
     * 设置缓存
     */
    public void setCache(String key, Object value, long timeout, TimeUnit unit) {
        cacheRedisTemplate.opsForValue().set(key, value, timeout, unit);
    }

    /**
     * 获取缓存
     */
    public Object getCache(String key) {
        return cacheRedisTemplate.opsForValue().get(key);
    }

    /**
     * 删除缓存
     */
    public Boolean deleteCache(String key) {
        return cacheRedisTemplate.delete(key);
    }

    /**
     * 检查缓存是否存在
     */
    public Boolean hasCache(String key) {
        return cacheRedisTemplate.hasKey(key);
    }

    /**
     * 设置缓存过期时间
     */
    public Boolean expireCache(String key, long timeout, TimeUnit unit) {
        return cacheRedisTemplate.expire(key, timeout, unit);
    }

    /**
     * 获取缓存剩余过期时间
     */
    public Long getCacheExpire(String key) {
        return cacheRedisTemplate.getExpire(key);
    }

    // ==================== 会话管理 ====================

    /**
     * 设置用户会话
     */
    public void setUserSession(String userId, Map<String, Object> sessionData, long timeout, TimeUnit unit) {
        sessionRedisTemplate.opsForValue().set(userId, sessionData, timeout, unit);
    }

    /**
     * 获取用户会话
     */
    @SuppressWarnings("unchecked")
    public Map<String, Object> getUserSession(String userId) {
        Object session = sessionRedisTemplate.opsForValue().get(userId);
        return session != null ? (Map<String, Object>) session : null;
    }

    /**
     * 删除用户会话
     */
    public Boolean deleteUserSession(String userId) {
        return sessionRedisTemplate.delete(userId);
    }

    /**
     * 刷新用户会话过期时间
     */
    public Boolean refreshUserSession(String userId, long timeout, TimeUnit unit) {
        return sessionRedisTemplate.expire(userId, timeout, unit);
    }

    /**
     * 检查用户是否在线
     */
    public Boolean isUserOnline(String userId) {
        return sessionRedisTemplate.hasKey(userId);
    }

    // ==================== 分布式锁 ====================

    /**
     * 尝试获取分布式锁
     */
    public Boolean tryLock(String lockKey, String lockValue, long timeout, TimeUnit unit) {
        Boolean result = lockRedisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, timeout, unit);
        return result != null && result;
    }

    /**
     * 释放分布式锁
     */
    public Boolean releaseLock(String lockKey, String lockValue) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = lockRedisTemplate.execute(
            new org.springframework.data.redis.core.script.DefaultRedisScript<>(script, Long.class),
            java.util.Collections.singletonList(lockKey),
            lockValue
        );
        return result != null && (Long) result == 1L;
    }

    /**
     * 检查锁是否存在
     */
    public Boolean isLocked(String lockKey) {
        return lockRedisTemplate.hasKey(lockKey);
    }

    /**
     * 获取锁的值
     */
    public String getLockValue(String lockKey) {
        return lockRedisTemplate.opsForValue().get(lockKey);
    }

    // ==================== 支付业务相关缓存 ====================

    /**
     * 缓存支付订单信息
     */
    public void cachePaymentOrder(String orderId, Map<String, Object> orderInfo) {
        setCache("order:" + orderId, orderInfo, 30, TimeUnit.MINUTES);
    }

    /**
     * 获取缓存的支付订单信息
     */
    @SuppressWarnings("unchecked")
    public Map<String, Object> getCachedPaymentOrder(String orderId) {
        Object order = getCache("order:" + orderId);
        return order != null ? (Map<String, Object>) order : null;
    }

    /**
     * 缓存用户支付信息
     */
    public void cacheUserPaymentInfo(String userId, Map<String, Object> paymentInfo) {
        setCache("user_payment:" + userId, paymentInfo, 1, TimeUnit.HOURS);
    }

    /**
     * 获取缓存的用户支付信息
     */
    @SuppressWarnings("unchecked")
    public Map<String, Object> getCachedUserPaymentInfo(String userId) {
        Object paymentInfo = getCache("user_payment:" + userId);
        return paymentInfo != null ? (Map<String, Object>) paymentInfo : null;
    }

    /**
     * 支付订单分布式锁
     */
    public Boolean lockPaymentOrder(String orderId, String lockValue) {
        return tryLock("payment_order:" + orderId, lockValue, 5, TimeUnit.MINUTES);
    }

    /**
     * 释放支付订单锁
     */
    public Boolean unlockPaymentOrder(String orderId, String lockValue) {
        return releaseLock("payment_order:" + orderId, lockValue);
    }

    /**
     * 用户支付操作分布式锁
     */
    public Boolean lockUserPayment(String userId, String lockValue) {
        return tryLock("user_payment:" + userId, lockValue, 3, TimeUnit.MINUTES);
    }

    /**
     * 释放用户支付操作锁
     */
    public Boolean unlockUserPayment(String userId, String lockValue) {
        return releaseLock("user_payment:" + userId, lockValue);
    }

    // ==================== Redis集群状态监控 ====================

    /**
     * 获取Redis集群信息
     */
    public Map<String, Object> getRedisClusterInfo() {
        Map<String, Object> info = new HashMap<>();
        
        try {
            // 获取Redis连接信息
            org.springframework.data.redis.connection.RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
            
            // 基本信息
            info.put("connected", true);
            info.put("connection_type", "cluster");
            info.put("timestamp", System.currentTimeMillis());
            
            // 测试基本操作
            String testKey = "health_check_" + System.currentTimeMillis();
            redisTemplate.opsForValue().set(testKey, "test", 10, TimeUnit.SECONDS);
            String testValue = (String) redisTemplate.opsForValue().get(testKey);
            redisTemplate.delete(testKey);
            
            info.put("read_write_test", "test".equals(testValue) ? "success" : "failed");
            
            connection.close();
            
        } catch (Exception e) {
            info.put("connected", false);
            info.put("error", e.getMessage());
        }
        
        return info;
    }

    /**
     * 获取Redis使用统计
     */
    public Map<String, Object> getRedisUsageStats() {
        Map<String, Object> stats = new HashMap<>();
        
        try {
            // 获取缓存键统计
            Set<String> cacheKeys = cacheRedisTemplate.keys("*");
            Set<String> sessionKeys = sessionRedisTemplate.keys("*");
            Set<String> lockKeys = lockRedisTemplate.keys("*");
            
            stats.put("cache_keys_count", cacheKeys != null ? cacheKeys.size() : 0);
            stats.put("session_keys_count", sessionKeys != null ? sessionKeys.size() : 0);
            stats.put("lock_keys_count", lockKeys != null ? lockKeys.size() : 0);
            stats.put("total_keys_count", 
                (cacheKeys != null ? cacheKeys.size() : 0) + 
                (sessionKeys != null ? sessionKeys.size() : 0) + 
                (lockKeys != null ? lockKeys.size() : 0));
            
            stats.put("status", "success");
            stats.put("timestamp", System.currentTimeMillis());
            
        } catch (Exception e) {
            stats.put("status", "error");
            stats.put("error", e.getMessage());
        }
        
        return stats;
    }

    /**
     * 清理过期的缓存和会话
     */
    public Map<String, Object> cleanupExpiredData() {
        Map<String, Object> result = new HashMap<>();
        int cleanedCount = 0;
        
        try {
            // 这里可以实现具体的清理逻辑
            // 由于Redis会自动清理过期键，这里主要是统计和监控
            
            result.put("status", "success");
            result.put("cleaned_count", cleanedCount);
            result.put("message", "清理完成");
            result.put("timestamp", System.currentTimeMillis());
            
        } catch (Exception e) {
            result.put("status", "error");
            result.put("error", e.getMessage());
        }
        
        return result;
    }
}